/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.to.aboomy.bannersample.component;

import com.to.aboomy.bannersample.ResourceTable;
import com.to.aboomy.bannersample.adapter.FragmentBannerAdapter;
import com.to.aboomy.bannersample.bean.BannerBean;
import com.to.aboomy.bannersample.bean.TextBean;
import com.to.aboomy.bannersample.util.Utils;
import com.to.aboomy.bannersample.util.loading.LoadingView;
import ohos.agp.animation.AnimatorProperty;
import ohos.agp.utils.Color;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.ListContainer;
import ohos.agp.components.LayoutScatter;
import ohos.agp.window.service.Display;
import ohos.agp.window.service.DisplayAttributes;
import ohos.agp.window.service.DisplayManager;
import ohos.app.Context;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.multimodalinput.event.TouchEvent;

import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import static ohos.multimodalinput.event.TouchEvent.POINT_MOVE;
import static ohos.multimodalinput.event.TouchEvent.PRIMARY_POINT_DOWN;
import static ohos.multimodalinput.event.TouchEvent.PRIMARY_POINT_UP;

/**
 * BannerAndList
 *
 * @since 2021-07-22
 */
public class BannerAndList extends DirectionalLayout implements Component.TouchEventListener {
    private static final float NUM_F_0_1 = 0.1f;
    private static final float NUM_F_0_2 = 0.2f;
    private static final float NUM_F_0_85 = 0.85f;
    private static final float NUM_F_500 = 500f;
    private static final int NUM_45 = 45;
    private static final int NUM_50 = 50;
    private static final int NUM_10 = 10;
    private static final int NUM_2000 = 2000;
    private static final int NUM_700 = 700;
    private static final int NUM_200 = 200;
    private static final int NUM_100 = 100;
    private static final int NUM_400 = 400;
    private static final int NUM_500 = 500;
    private static final int NUM_N_100 = -100;
    private static final int NUM_N_50 = -50;
    private static final int NUM_2 = 2;
    private static final int NUM_4 = 4;

    // 两次点击按钮之间的点击间隔不能少于1000毫秒
    private static final int MIN_CLICK_DELAY_TIME = NUM_2000;
    private int widthPm;
    private LoadingView loadingView;
    private DirectionalLayout mLoadingView;
    private Component root;
    private FragmentBannerAdapter bannerAdapter;
    private ListContainer mRecyclerView;
    private long lastClickTime = 0L;
    /**
     * listContainer是否滑到顶部
     */
    private boolean isTop = true;
    private int scrolltop = 1;
    private float downY;
    private float moveY;
    private float mOffsetY;
    private AnimatorProperty mAnimatorProperty;

    /**
     * 构造
     *
     * @param context
     */
    public BannerAndList(Context context) {
        this(context, null);
    }

    /**
     * 构造
     *
     * @param context
     * @param attrSet
     */
    public BannerAndList(Context context, AttrSet attrSet) {
        this(context, attrSet, null);
    }

    /**
     * 构造
     *
     * @param context
     * @param attrSet
     * @param styleName
     */
    public BannerAndList(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);

        Optional<Display>
                display = DisplayManager.getInstance().getDefaultDisplay(this.getContext());
        DisplayAttributes displayAttributes = display.get().getAttributes();
        widthPm = displayAttributes.width;

        bannerAdapter = new FragmentBannerAdapter(mContext);
        Component rootView = LayoutScatter.getInstance(context).parse(ResourceTable.Layout_fragment_test_item,
                this, true);
        mRecyclerView = (ListContainer) rootView.findComponentById(ResourceTable.Id_xRecyclerView);
        root = rootView.findComponentById(ResourceTable.Id_root);
        mLoadingView = (DirectionalLayout) rootView.findComponentById(ResourceTable.Id_loading_view);
        loadingView = (LoadingView) rootView.findComponentById(ResourceTable.Id_progress_loading);

        initView();
        loadData();
        mRecyclerView.setItemProvider(bannerAdapter);
    }

    private void initView() {
        setTopHide();
        mRecyclerView.setTouchEventListener(this);
        root.setTouchEventListener(this::onTouchEvent);
        loadingView.setBindStateChangedListener(loadingView);
        loadingView.setPaintcolor(Color.getIntColor("#000000"));
        loadingView.setSize(NUM_45);
        loadingView.stopAnimation();

        // 默认进度条的位置
        mLoadingView.setScaleX(NUM_F_0_2);
        mLoadingView.setScaleY(NUM_F_0_2);
        mLoadingView.setPosition(widthPm / NUM_2 - NUM_50, NUM_N_100);

        mRecyclerView.addScrolledListener(new Component.ScrolledListener() {
            @Override
            public void onContentScrolled(Component component, int scrollX,
                                          int scrollY, int oldScrollX, int oldScrollY) {
                isTop = scrollY == 0;
            }
        });
    }

    private void loadData() {
        BannerBean bannerBean = new BannerBean();
        bannerBean.urls = new ArrayList<>();
        bannerBean.itemType = NUM_4;
        int count = new SecureRandom().nextInt(NUM_4) + 1;
        for (int index = 0; index < count; index++) {
            bannerBean.urls.add(Utils.getRandomImage());
        }
        List<Object> list = new ArrayList<>();
        list.add(bannerBean);

        for (int index = 0; index < NUM_200; index++) {
            TextBean textBean = new TextBean();
            textBean.text = "--- " + index;
            list.add(textBean);
        }
        bannerAdapter.setData(list);
    }

    @Override
    public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
        switch (touchEvent.getAction()) {
            case PRIMARY_POINT_DOWN:
                if (isTop && timeRecord()) {
                    downY = touchEvent.getPointerScreenPosition(0).getY();
                }
                return true;
            case POINT_MOVE:
                if (scrolltop == 1) {
                    touchPointMove(touchEvent);
                }
                return true;
            case PRIMARY_POINT_UP:
                touchPrimaryPoint(touchEvent);
                return false;
            default:
        }
        return true;
    }

    private void touchPointMove(TouchEvent touchEvent) {
        if (timeRecord()) {
            moveY = touchEvent.getPointerScreenPosition(touchEvent.getIndex()).getY();
            mOffsetY = Math.min(moveY - downY, NUM_700);
            if (mOffsetY > NUM_10 && isTop && (moveY - downY) < NUM_700) {
                touchPointMoveChild();
                mOffsetY = moveY - downY;
                mLoadingView.setPosition(widthPm / NUM_2 - NUM_50, (int) mOffsetY - NUM_50);
                root.invalidate();
            }
        }
    }

    private void touchPointMoveChild() {
        if ((moveY - downY) <= NUM_400) {
            float scaleSize = mOffsetY / NUM_F_500;
            if (scaleSize > NUM_F_0_1) {
                mLoadingView.setScaleX(scaleSize);
                mLoadingView.setScaleY(scaleSize);
            } else {
                mLoadingView.setScaleX(NUM_F_0_2);
                mLoadingView.setScaleY(NUM_F_0_2);
            }
        } else {
            mLoadingView.setScaleX(NUM_F_0_85);
            mLoadingView.setScaleY(NUM_F_0_85);
        }
    }

    private void touchPrimaryPoint(TouchEvent touchEvent) {
        if (scrolltop == 1) {
            if (timeRecord()) {
                mOffsetY = Math.min(moveY - downY, NUM_700);
                if (mOffsetY < NUM_400) {
                    AnimatorProperty animatorProperty = mLoadingView.createAnimatorProperty();
                    animatorProperty.setDuration(NUM_500).setDelay(NUM_100).scaleX(0).scaleY(0);
                    animatorProperty.start();

                    AnimatorProperty animatorProperty2 = mLoadingView.createAnimatorProperty();
                    animatorProperty2.moveFromY(mOffsetY).moveToY(NUM_N_50)
                            .setDuration(NUM_500).setDelay(NUM_100);
                    animatorProperty2.start();
                } else {
                    moveY = touchEvent.getPointerScreenPosition(touchEvent.getIndex()).getY();
                    loadingView.startAnimation();

                    // 回退位置
                    animationFromTo();

                    // 设置 开始动画时间戳
                    lastClickTime = System.currentTimeMillis();
                    new EventHandler(EventRunner.getMainEventRunner()).postTask(new Runnable() {
                        @Override
                        public void run() {
                            loadingView.stopAnimation();
                            setTopHide();
                            lastClickTime = 0;
                        }
                    }, NUM_2000);
                    root.invalidate();
                    mOffsetY = 0;
                }
            }
        }
    }

    /**
     * setTopHide
     */
    public void setTopHide() {
        AnimatorProperty animatorProperty = mLoadingView.createAnimatorProperty();
        animatorProperty.setDuration(NUM_500).setDelay(NUM_10).scaleX(0).scaleY(0);
        animatorProperty.start();
        new EventHandler(EventRunner.getMainEventRunner()).postTask(new Runnable() {
            @Override
            public void run() {
                animatorProperty.stop();
                mLoadingView.setPosition(widthPm / NUM_2 - NUM_50, NUM_N_50);
                loadData();
                bannerAdapter.notifyDataChanged();
            }
        }, NUM_500);
    }

    /**
     * animationFromTo
     */
    public void animationFromTo() {
        mAnimatorProperty = mLoadingView.createAnimatorProperty();
        mAnimatorProperty.moveFromY(mOffsetY).moveToY(NUM_200).setDuration(NUM_500).setDelay(NUM_100);
        mAnimatorProperty.start();
    }

    /**
     * timeRecord
     *
     * @return boolean
     */
    public boolean timeRecord() {
        if (lastClickTime == 0) {
            return true;
        }
        long curClickTime = System.currentTimeMillis();
        if ((curClickTime - lastClickTime) >= MIN_CLICK_DELAY_TIME) {
            // 超过点击间隔后再将lastClickTime重置为当前点击时间
            lastClickTime = curClickTime;
            return true;
        }
        return false;
    }
}
